/**
	This file is part of Fighting Field.

	Fighting Field is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Fighting Field is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Fighting Field.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "Widget.h"

#include "OgreFontManager.h"
#include "OgreTextAreaOverlayElement.h"

namespace FF
{
	Widget::Widget()
	{
		mGuiLoc = TrayLocation::None;
		mElement = 0;
		mListener = 0;
	}

	void Widget::Cleanup()
	{
		if (mElement) NukeOverlayElement(mElement);
		mElement = 0;
	}

	void Widget::NukeOverlayElement(Ogre::OverlayElement* element)
	{
		Ogre::OverlayContainer* container = dynamic_cast<Ogre::OverlayContainer*>(element);
		if (container)
		{
			std::vector<Ogre::OverlayElement*> toDelete;

			Ogre::OverlayContainer::ChildIterator children = container->getChildIterator();
			while (children.hasMoreElements())
			{
				toDelete.push_back(children.getNext());
			}

			for (unsigned int i = 0; i < toDelete.size(); i++)
			{
				NukeOverlayElement(toDelete[i]);
			}
		}
		if (element)
		{
			Ogre::OverlayContainer* parent = element->getParent();
			if (parent) parent->removeChild(element->getName());
			Ogre::OverlayManager::getSingleton().destroyOverlayElement(element);
		}
	}

	bool Widget::IsCursorOver(Ogre::OverlayElement* element, const Ogre::Vector2& cursorPos, Ogre::Real voidBorder)
	{
		Ogre::OverlayManager& om = Ogre::OverlayManager::getSingleton();
		Ogre::Real l = element->_getDerivedLeft() * om.getViewportWidth();
		Ogre::Real t = element->_getDerivedTop() * om.getViewportHeight();
		Ogre::Real r = l + element->getWidth();
		Ogre::Real b = t + element->getHeight();

		return (cursorPos.x >= l + voidBorder && cursorPos.x <= r - voidBorder &&
			cursorPos.y >= t + voidBorder && cursorPos.y <= b - voidBorder);
	}

	Ogre::Vector2 Widget::CursorOffset(Ogre::OverlayElement* element, const Ogre::Vector2& cursorPos)
	{
		Ogre::OverlayManager& om = Ogre::OverlayManager::getSingleton();
		return Ogre::Vector2(cursorPos.x - (element->_getDerivedLeft() * om.getViewportWidth() + element->getWidth() / 2),
			cursorPos.y - (element->_getDerivedTop() * om.getViewportHeight() + element->getHeight() / 2));
	}

	Ogre::Real Widget::GetCaptionWidth(const Ogre::DisplayString& caption, Ogre::TextAreaOverlayElement* area)
	{
		Ogre::Font* font = (Ogre::Font*)Ogre::FontManager::getSingleton().getByName(area->getFontName()).getPointer();
		Ogre::String current = caption.asUTF8();
		Ogre::Real lineWidth = 0;

		for (unsigned int i = 0; i < current.length(); i++)
		{
			// be sure to provide a line width in the text area
			if (current[i] == ' ')
			{
				if (area->getSpaceWidth() != 0) lineWidth += area->getSpaceWidth();
				else lineWidth += font->getGlyphAspectRatio(' ') * area->getCharHeight();
			}
			else if (current[i] == '\n') break;
			// use glyph information to calculate line width
			else lineWidth += font->getGlyphAspectRatio(current[i]) * area->getCharHeight();
		}

		return (Ogre::Real)(unsigned int)lineWidth;
	}

	void Widget::FitCaptionToArea(const Ogre::DisplayString& caption, Ogre::TextAreaOverlayElement* area, Ogre::Real maxWidth)
	{
		Ogre::Font* f = (Ogre::Font*)Ogre::FontManager::getSingleton().getByName(area->getFontName()).getPointer();
		Ogre::String s = caption.asUTF8();

		int nl = s.find('\n');
		if (nl != -1) s = s.substr(0, nl);

		Ogre::Real width = 0;

		for (unsigned int i = 0; i < s.length(); i++)
		{
			if (s[i] == ' ' && area->getSpaceWidth() != 0) width += area->getSpaceWidth();
			else width += f->getGlyphAspectRatio(s[i]) * area->getCharHeight();
			if (width > maxWidth)
			{
				s = s.substr(0, i);
				break;
			}
		}

		area->setCaption(s);
	}

	Ogre::OverlayElement* Widget::GetOverlayElement()
	{
		return mElement;
	}

	const Ogre::String& Widget::GetName()
	{
		return mElement->getName();
	}

	TrayLocation::Val Widget::GetTrayLocation()
	{
		return mGuiLoc;
	}

	void Widget::Hide()
	{
		mElement->hide();
	}

	void Widget::Show()
	{
		mElement->show();
	}

	bool Widget::IsVisible()
	{
		return mElement->isVisible();
	}
}
